package cn.edu.zzuli.util;

import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

//@Data
@Component
public class AliOssUtils {

    // Endpoint以杭州为例，其它Region请按实际情况填写。
    private final String endpoint = "https://oss-cn-beijing.aliyuncs.com";
    // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
    private final String accessKeyId = "LTAI4GGUjEbah4mVgJjToj7p";

    private final String accessKeySecret = "uPGDG0gZuUidUHJvicpQBwG9DeYMR5";

    private final String bucketName = "ekij";

    private final String roleArn = "acs:ram::1000053667769116:role/suzy";

    private final String roleSessionName = "suzy";

    //默认时长六分钟
    int expire = 360 * 1000;

    /**
     * 获取 上传文件的 put url
     * @param objectName
     * @return put url
     */
    public URL getPutUrl(String objectName) {
        return this.putFile(objectName,null);
    }

    /**
     * 上传文件到 OSS， 不是直传的方式，因为我们后端直接接收这个文件了。
     * @param objectName 上传的 文件名
     * @param f 文件
     * @return 如果带上文件的话，返回的是上传后的 url文件地址。
     *          如果不上传文件的话，返回的是 签名地址。
     */
    public URL putFile(String objectName, File f) {
        OSS ossClient = getStsClient();

        Date expiration = new Date(new Date().getTime() + expire);

        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName);
        // HttpMethod为PUT。
        request.setMethod(HttpMethod.PUT);
        // 添加用户自定义元信息。 前端必须带上 "x-oss-meta-author":"ekij"
        request.addUserMetadata("author", "ekij");
        // 设置ContentType。
        request.setContentType("application/octet-stream");
        // 设置过期时间。
        request.setExpiration(expiration);
        // 生成签名URL
        URL signedUrl = ossClient.generatePresignedUrl(request);

        // 使用签名URL发送请求。
        if (f != null){
            InputStream fin = null;
            try {
                fin = new FileInputStream(f);
            } catch (FileNotFoundException e) {
                System.out.println("找不到文件");
            }
            // 添加PutObject请求头。
            Map<String, String> customHeaders = new HashMap<String, String>();
            customHeaders.put("Content-Type", "application/octet-stream");
            customHeaders.put("x-oss-meta-author", "ekij");

            //上传文件。
            PutObjectResult result = ossClient.putObject(signedUrl, fin, f.length(), customHeaders);
            return getUrl(objectName);
        }

        // 关闭OSSClient。
        ossClient.shutdown();
        return signedUrl;
    }

    /**
     * 获取 sts 授权
     * @return url
     */
    public URL getUrl(String objectName) {
        //采取默认的过期时间
        return this.getUrl(objectName,expire);
    }

    //自定义过期时间
    public URL getUrl(String objectName, int expire) {
        try {
            // 创建OSSClient实例。
            OSS ossClient = getStsClient();

            // 设置URL过期时间
            Date expiration = new Date(new Date().getTime() + expire);
            // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
            URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
            // 关闭OSSClient。
            ossClient.shutdown();
            return url;
        }catch (Exception e){
            return null;
        }

    }


    /**
     * 获取 临时令牌 sts
     * @return 返回 ossClient对象
     */
    public OSSClient getStsClient() {

        String policy = "{\n" +
                "    \"Version\": \"1\",\n" +
                "    \"Statement\": [\n" +
                "        {\n" +
                "            \"Effect\": \"Allow\",\n" +
                "            \"Action\": [\n" +
                "                \"oss:Put*\",\n" +
                "                \"oss:Post*\",\n" +
                "                \"oss:Get*\"\n" +
                "            ],\n" +
                "            \"Resource\": [\n" +
                "                \"acs:oss:*:*:ekij/*\"\n" +
                "            ]\n" +
                "        }\n" +
                "    ]\n" +
                "}";
        try {
            // 添加endpoint（直接使用STS endpoint，前两个参数留空，无需添加region ID）
            DefaultProfile.addEndpoint("", "", "Sts", "sts.aliyuncs.com");
            // 构造default profile（参数留空，无需添加region ID）
            IClientProfile profile = DefaultProfile.getProfile("", accessKeyId, accessKeySecret);
            // 用profile构造client
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(policy); // 若policy为空，则用户将获得该角色下所有权限
            request.setDurationSeconds(1000L); // 设置凭证有效时间
            request.setConnectTimeout(10000);
            request.setReadTimeout(10000);
            final AssumeRoleResponse response = client.getAcsResponse(request);
//            System.out.println("Expiration: " + response.getCredentials().getExpiration());
//            System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
//            System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
//            System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
//            System.out.println("RequestId: " + response.getRequestId());

            String ossAccessKeyId = response.getCredentials().getAccessKeyId();
            String ossAccessKeySecret = response.getCredentials().getAccessKeySecret();
            String ossSecurityToken = response.getCredentials().getSecurityToken();

            return new OSSClient(endpoint,
                    (CredentialsProvider)(new DefaultCredentialProvider(ossAccessKeyId, ossAccessKeySecret, ossSecurityToken)),
                    (ClientConfiguration)null);

        } catch (ClientException e) {
            System.out.println("Failed：");
            System.out.println("Error code: " + e.getErrCode());
            System.out.println("Error message: " + e.getErrMsg());
            System.out.println("RequestId: " + e.getRequestId());

            return null;
        }
    }

}
